package org.dashboard.client.widget.serversup;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Node;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.rpc.ServiceDefTarget;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.Widget;
import org.dashboard.client.widget.alarm.Alarm;
import org.dashboard.shared.Props;
import org.dashboard.shared.serversup.ServerInfo;

import java.util.ArrayList;
import java.util.Iterator;

/**
 * @author Simon Vogensen, Lakeside
 * @version $Revision$
 */
public class ServersUpWidget extends SimplePanel {

    private Alarm alarm;

    interface Binder extends UiBinder<Widget, ServersUpWidget> { }
    private static final Binder binder = GWT.create(Binder.class);

    public ServersUpWidget(String width, String height, int refreshInterval) {
        super();

        setWidget(binder.createAndBindUi(this));
        
        final Node node = getElement().getChild(0);
        DOM.setStyleAttribute((Element) node, "width", width);
        DOM.setStyleAttribute((Element) node, "height", height);

        final ServersUpServiceAsync instance = (ServersUpServiceAsync) GWT.create(ServersUpService.class);
        String url = GWT.getModuleBaseURL() + "serversup";
        ((ServiceDefTarget) instance).setServiceEntryPoint(url);

        final AsyncCallback<ArrayList<ServerInfo>> statesAsyncCallback = new AsyncCallback<ArrayList<ServerInfo>>() {
            public ArrayList<ServerInfo> oldServerInfoList;

            public void onFailure(Throwable caught) {
                // dont want failed alert on dashboard
//                Window.alert(caught.getMessage());
            }

            public void onSuccess(ArrayList<ServerInfo> result) {
                if(isChanged(result, oldServerInfoList)) {
                    Node rootNode = node.getChild(0).getChild(1);
                    StringBuilder sb = new StringBuilder();
                    String[] colNames = Props.instance().getServersUpConfig().get(0);
                    String[] rowNames = Props.instance().getServersUpConfig().get(1);
                    Iterator<ServerInfo> serverInfoIterator = result.iterator();
                    sb.append("<table><tr><td></td>");
                    for (String colName : colNames) {
                        sb.append("<td style=\"font-size: 25px;font-weight: bold;\">"+colName+"</td>");
                    }
                    sb.append("</tr>");
                    for (String rowName : rowNames) {
                        sb.append("<tr>");
                        sb.append("<td style=\"font-size: 25px;font-weight: bold;\">"+rowName+"</td>");
                        for (String colName : colNames) {
                            ServerInfo serverInfo = serverInfoIterator.next();
                            sb.append("<td>");
                            sb.append("<object alt=\""+serverInfo.getServerURL()+"\" type=\"image/svg+xml\"" +
                                    " style=\"border:none; width:55px; height:55px; background-color: rgba(0, 0, 0, 0);\"" +
                                    " data=\""+(serverInfo.isAlive()? "serverup.svg" :"serverdown.svg")+"\"></object>");
                            sb.append("</td>");
                        }
                        sb.append("</tr>");
                    }
                    sb.append("</table>");
                    ((Element)rootNode).setInnerHTML(sb.toString());
                    startOrStopAlarm(result.iterator());
                }
                this.oldServerInfoList = result;
            }

            private boolean isChanged(ArrayList<ServerInfo> serverInfoList, ArrayList<ServerInfo> oldServerInfoList) {
                if(oldServerInfoList == null) return true;
                for (ServerInfo serverInfo : serverInfoList) {
                    if(serverInfo.isAlive() != oldServerInfoList.get(oldServerInfoList.indexOf(serverInfo)).isAlive()) {
                        return true;
                    }
                }
                return false;
            }
        };
        final Timer timer = new Timer() {
            @Override
            public void run() {
                instance.getStates(statesAsyncCallback);
            }
        };
        timer.scheduleRepeating(refreshInterval);

        instance.getStates(statesAsyncCallback);
    }

    private void startOrStopAlarm(Iterator<ServerInfo> iterator) {
        boolean allAlive = true;
        while (iterator.hasNext()) {
            ServerInfo next = iterator.next();
            if (!next.isAlive()) {
                alarm.start();
                allAlive = false;
            }
        }
        if (allAlive) {
            alarm.stop();
        }
    }

    public void setAlarm(Alarm alarm){
        this.alarm = alarm;
    }
}
